package aes

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"fmt"
	"io"
	"os"
)

// EncryptFile AES文本加密 (AES-256-CFB) 流模式，适合处理大文件
func EncryptFile(inputFilePath, outputFilePath, key string) error {
	// 验证密钥长度 (必须为 16, 24, 或 32 字节)
	keyBytes := []byte(key)
	if len(keyBytes) != 16 && len(keyBytes) != 24 && len(keyBytes) != 32 {
		return fmt.Errorf("key length must be 16, 24, or 32 bytes")
	}

	// 打开输入文件
	inputFile, err := os.Open(inputFilePath)
	if err != nil {
		return fmt.Errorf("failed to open input file: %w", err)
	}
	defer func(inputFile *os.File) {
		err := inputFile.Close()
		if err != nil {
		}
	}(inputFile)

	// 创建输出文件
	outputFile, err := os.Create(outputFilePath)
	if err != nil {
		return fmt.Errorf("failed to create output file: %w", err)
	}
	defer func(outputFile *os.File) {
		err := outputFile.Close()
		if err != nil {
		}
	}(outputFile)

	// 创建 AES 密码块
	block, err := aes.NewCipher(keyBytes)
	if err != nil {
		return fmt.Errorf("failed to create cipher: %w", err)
	}

	// 生成随机 IV（初始化向量）
	iv := make([]byte, aes.BlockSize)
	if _, err = io.ReadFull(rand.Reader, iv); err != nil {
		return fmt.Errorf("failed to generate IV: %w", err)
	}

	// 将 IV 写入输出文件
	if _, err = outputFile.Write(iv); err != nil {
		return fmt.Errorf("failed to write IV: %w", err)
	}

	// 创建流加密器
	stream := cipher.NewCFBEncrypter(block, iv)

	// 创建加密流写入器
	writer := &cipher.StreamWriter{S: stream, W: outputFile}

	// 将输入文件内容加密后写入输出文件
	if _, err := io.Copy(writer, inputFile); err != nil {
		return fmt.Errorf("failed to encrypt file: %w", err)
	}

	return nil
}

// DecryptFile AES文本解密 (AES-256-CFB) 流模式，适合处理大文件
func DecryptFile(inputFilePath, outputFilePath, key string) error {
	keyBytes := []byte(key)
	if len(keyBytes) != 16 && len(keyBytes) != 24 && len(keyBytes) != 32 {
		return fmt.Errorf("key length must be 16, 24, or 32 bytes")
	}

	inputFile, err := os.Open(inputFilePath)
	if err != nil {
		return fmt.Errorf("failed to open input file: %w", err)
	}
	defer func(inputFile *os.File) {
		err := inputFile.Close()
		if err != nil {
		}
	}(inputFile)

	outputFile, err := os.Create(outputFilePath)
	if err != nil {
		return fmt.Errorf("failed to create output file: %w", err)
	}
	defer func(outputFile *os.File) {
		err := outputFile.Close()
		if err != nil {
		}
	}(outputFile)

	block, err := aes.NewCipher(keyBytes)
	if err != nil {
		return fmt.Errorf("failed to create cipher: %w", err)
	}

	iv := make([]byte, aes.BlockSize)
	if _, err := io.ReadFull(inputFile, iv); err != nil {
		return fmt.Errorf("failed to read IV: %w", err)
	}

	stream := cipher.NewCFBDecrypter(block, iv)
	reader := &cipher.StreamReader{S: stream, R: inputFile}

	if _, err := io.Copy(outputFile, reader); err != nil {
		return fmt.Errorf("failed to decrypt file: %w", err)
	}

	return nil
}
